package org.testtools.util;

import java.text.DecimalFormat;
import java.util.UUID;

public class IdGenUtil {

    private static final String ZERO = "0";

    private static final String EMPTY = "";

    private static final String ID = "id_";

    private static final String MATCH_AZ_UNDERSCORE = "[A-Za-z_]";

    private static final String SEMICOLON = ";";

    private static final String COLON = ",";

    private static final String DOT = ".";

    private static final String PLUS = "+";

    private static final String BLANK = " ";

    private static final String UNDERSCORE = "_";

    private static final String ASTERISK = "*";

    private static final String HYPHEN = "-";

    public synchronized static String getHexaId() {
        return UUID.randomUUID().toString().replaceAll(HYPHEN, EMPTY).toUpperCase();
    }

    public static String getNewHexaId(final int length) {
        return getHexaId().substring(0, length);
    }

    public synchronized static String getNewId(final int length) {
        final StringBuffer sb = new StringBuffer(ID);
        final String idTemp = getHexaId();

        if (length <= idTemp.length())
            sb.append(idTemp);
        else
            for (int i = 0; i < getOffset(length, idTemp); i++)
                sb.append(getHexaId());

        return sb.substring(0, length);
    }

    public static String getIntId(int length) {
        StringBuffer pattern = new StringBuffer(length);

        for (int i = 0; i < length; i++) {
            pattern.append(ZERO);
        }

        double number = System.nanoTime();
        double pow = Math.pow(10, 1 + length);

        if (number > pow)
            number -= pow;

        String result = new DecimalFormat(pattern.toString()).format(number);

        if (result.length() > length) {
            result = result.substring(result.length() - length);
        }

        return result;
    }

    public static String getIdWithPattern(String pattern) {
        return getIdWithPattern(pattern, pattern.length());
    }

    public static String getIdWithPattern(String pattern, int length) {
        int fixedLength = pattern.replaceAll("0|#", EMPTY).length();
        return new DecimalFormat(pattern).format(getIdAsDouble(length - fixedLength));
    }

    public static double getIdAsDouble(int length) {
        return Double.parseDouble(getIntId(length));
    }

    public synchronized static String getNewId(final Integer alias, final int length) {
        return getNewId(alias.toString(), length);
    }

    public synchronized static String getNewId(String newAlias, final int length) {
        newAlias = newAlias.trim();
        final StringBuffer sb = new StringBuffer((!newAlias.substring(0, 1).matches(MATCH_AZ_UNDERSCORE) ? ID : EMPTY) + newAlias).append(UNDERSCORE.toCharArray());
        final String idTemp = getHexaId();

        final int factor = length / idTemp.length() + (length % idTemp.length() > 0 ? 1 : 0);

        if (length <= idTemp.length())
            sb.append(idTemp);
        else
            for (int i = 0; i < factor; i++)
                sb.append(getHexaId());

        return sb.substring(0, length).replace(HYPHEN, UNDERSCORE).replace(ASTERISK, UNDERSCORE).replace(BLANK, UNDERSCORE).replace(PLUS, UNDERSCORE).replace(DOT, UNDERSCORE)
                        .replace(COLON, UNDERSCORE).replace(SEMICOLON, UNDERSCORE);
    }

    private static int getOffset(final int length, String idTemp) {
        int factor = length / idTemp.length() + (length % idTemp.length() > 0 ? 1 : 0);
        return factor;
    }
}
